package com.xthink.web.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xthink.common.constant.HttpStatus;
import com.xthink.common.result.AjaxResult;
import com.xthink.common.utils.JwtUtil;
import com.xthink.common.utils.RedisCache;
import com.xthink.common.dto.user.UserListDto;
import com.xthink.common.pojo.sys.UserRole;
import com.xthink.common.vo.user.*;
import com.xthink.common.pojo.user.User;
import com.xthink.web.config.LoginUser;
import com.xthink.web.mapper.UserMapper;
import com.xthink.web.mapper.UserRoleMapper;
import com.xthink.web.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserRoleMapper userRoleMapper;


    @Autowired
    private PasswordEncoder passwordEncoder;
    //账号注册
    @Override
    public AjaxResult register(UserRegisterVo userVo) {
        if (!StringUtils.isNotBlank(userVo.getName())){//检测姓名是否为空
            return AjaxResult.error("请输入您的姓名");
        }

        if (!StringUtils.isNotBlank(userVo.getPhone())){//检测手机号是否为空
            return AjaxResult.error("请输入您的手机号");
        }

        //查询用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone,userVo.getPhone());
        wrapper.eq(User::getBusinessName,userVo.getBusinessName());
        User User = userMapper.selectOne(wrapper);

        if (User!=null){
            return AjaxResult.error("该手机号已被注册或经销商名称已被注册");
        }


        if (!StringUtils.isNotBlank(userVo.getInputBox())){
            return AjaxResult.error("请输入验证码");
        }

        if (StringUtils.isNotBlank(userVo.getInputBox())){
            if (!userVo.getImageCode().equals(userVo.getInputBox())){
                return AjaxResult.error("您输入的验证码有误，请重新输入");
            }
        }

        if (!StringUtils.isNotBlank(userVo.getInputSms())){
            return AjaxResult.error("请输入短信验证码");
        }

        //从redis中对比验证码
        String code = redisCache.getCacheObject(userVo.getPhone());

        if (!userVo.getInputBox().equals(code)){
            return AjaxResult.error("您输入的短信验证码有误，请重新输入");
        }

        if (!StringUtils.isNotBlank(userVo.getPassword())){
            return AjaxResult.error("请输入您的密码");
        }else if (!StringUtils.isNotBlank(userVo.getPasswordTwo())){
            return AjaxResult.error("请确认您的密码");
        }else if (!userVo.getPassword().equals(userVo.getPasswordTwo())){
            return AjaxResult.error("两次密码不一致");
        }else if (userVo.getPlatformAgreement()==0){
            return AjaxResult.error("请勾选我已阅读并同意");
        }else if (!StringUtils.isNotBlank(userVo.getBusinessName())){
            return AjaxResult.error("请输入您的企业名称");
        }

        User user = new User();

        BeanUtils.copyProperties(userVo,user);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        int insert = userMapper.insert(user);
        if (insert==0){
            return AjaxResult.error("注册失败");
        }

        return AjaxResult.success(HttpStatus.SUCCESS);
    }

    //账号登录
    @Override
    public AjaxResult login(UserLoginVo userLoginVo) {

        if (!StringUtils.isNotBlank(userLoginVo.getInputBox())){
            return AjaxResult.error("请输入验证码");
        }

        if (StringUtils.isNotBlank(userLoginVo.getInputBox())){
            if (!userLoginVo.getImageCode().equals(userLoginVo.getInputBox())){
                return AjaxResult.error("您输入的验证码有误，请重新输入");
            }
        }

        //AuthenticationManager authenticate进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userLoginVo.getPhone(), userLoginVo.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        //如果认证没通过，给出对应的提示
        if (authenticate==null){
            throw new RuntimeException("登录失败,用户名或密码错误");
        }

        //如果认证通过了，使用userid生成一个jwt jwt存入AjaxResult返回
        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        Map<String, String> map = new HashMap<>();
        map.put("userToken",jwt);

        //判断是否为管理员
        User user = userMapper.selectById(userId);
        Integer type = user.getType();
        if (type==1){//表示身份为管理员
            String name = user.getName();
            redisCache.setCacheObject("adminName",name);//存入名字 后面操作的时候记录操作内容
        }
        //把完整的用户信息存入redis userId作为key
        redisCache.setCacheObject("login:"+userId,loginUser);
        //return new AjaxResult(HttpStatus.SUCCESS,"登录成功",map);
        System.out.println("发送token："+map);

        //设置最后登录时间
        DateTime date = DateUtil.date();
        String dateString = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getPhone,userLoginVo.getPhone())
                .set(User::getLastTime,dateString);
        return AjaxResult.success("登录成功",map);
    }

    //密码找回
    @Override
    public AjaxResult retrieve(UserRetrieveVo userRetrieveVo) {

        if (!StringUtils.isNotBlank(userRetrieveVo.getPhone())){//检测手机号是否为空
            return AjaxResult.error("请输入您的手机号");
        }

        if (!StringUtils.isNotBlank(userRetrieveVo.getInputBoxImage())){
            return AjaxResult.error("请输入您的验证码");
        }

        if (!StringUtils.isNotBlank(userRetrieveVo.getInputBox())){
            return AjaxResult.error("请输入您的短信验证码");
        }

        if (!StringUtils.isNotBlank(userRetrieveVo.getPassword())){
            return AjaxResult.error("请输入您的密码");
        }

        if (!userRetrieveVo.getPassword().equals(userRetrieveVo.getPasswordTwo())){
            return AjaxResult.error("两次密码不一致");
        }

        if (userRetrieveVo.getImageCode().equals(userRetrieveVo.getInputBoxImage())){
            return AjaxResult.error("您输入的验证码有误，请重新输入");
        }

        //从redis中对比验证码
        String code = redisCache.getCacheObject(userRetrieveVo.getPhone());

        if (!userRetrieveVo.getInputBox().equals(code)){
            return AjaxResult.error("您输入的短信验证码有误，请重新输入");
        }

        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("phone",userRetrieveVo.getPhone())
                .set("password",passwordEncoder.encode(userRetrieveVo.getPassword()));
        int update = userMapper.update(null, wrapper);

        if (update==0){
           return AjaxResult.error(HttpStatus.CREATED,"密码修改失败");
        }

        return AjaxResult.success("密码修改成功");
    }

    //插入经销商
    @Override
    public AjaxResult insert(UserInsertVo userInsertVo) {

        if (!StringUtils.isNotBlank(userInsertVo.getBusinessName())){
            return AjaxResult.error("请输入您的企业名称");
        }

        if (!StringUtils.isNotBlank(userInsertVo.getName())){
            return AjaxResult.error("请输入负责人的姓名");
        }

        if (!StringUtils.isNotBlank(userInsertVo.getPhone())){
            return AjaxResult.error("请输入您的手机号");
        }

        //查询用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone,userInsertVo.getPhone());
        wrapper.eq(User::getBusinessName,userInsertVo.getBusinessName());
        User User = userMapper.selectOne(wrapper);
        if (User!=null){
            return AjaxResult.error("该手机号已被注册或经销商名称已被注册");
        }

        if (!StringUtils.isNotBlank(userInsertVo.getPassword())){
            return AjaxResult.error("请输入您的密码");
        }


        User user = new User();
        BeanUtils.copyProperties(userInsertVo,user);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setType(0);
        user.setAccountStatus(1);
        int insert = userMapper.insert(user);
        if (insert==0){
            return AjaxResult.error("添加失败");
        }
        return AjaxResult.success();
    }

    //管理员添加
    @Override
    public AjaxResult adminInsert(AdminInsertVo adminInsertVo) {

        if (adminInsertVo.getRoleId()==null){
            return AjaxResult.error("请选择组别");
        }

        if (!StringUtils.isNotBlank(adminInsertVo.getName())){
            return AjaxResult.error("请输入您的姓名");
        }

        if (!StringUtils.isNotBlank(adminInsertVo.getPhone())){
            return AjaxResult.error("请输入您的手机号");
        }

        //查询用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone,adminInsertVo.getPhone());
        User User = userMapper.selectOne(wrapper);
        if (User!=null){
            return AjaxResult.error("该手机号已被注册");
        }

        if (!StringUtils.isNotBlank(adminInsertVo.getPassword())){
            return AjaxResult.error("请输入您的密码");
        }

        User user = new User();
        BeanUtils.copyProperties(adminInsertVo,user);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setType(1);
        user.setAccountStatus(1);
        int insert = userMapper.insert(user);
        if (insert==0){
            return AjaxResult.error("添加失败");
        }
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(adminInsertVo.getRoleId());
        userRoleMapper.insert(userRole);
        return AjaxResult.success();
    }

    //管理员编辑
    @Override
    public AjaxResult adminUpdate(AdminUpdateVo adminUpdateVo) {
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getId,adminUpdateVo.getId())
                .set(StringUtils.isNotBlank(adminUpdateVo.getName()),User::getName,adminUpdateVo.getName())
                .set(StringUtils.isNotBlank(adminUpdateVo.getPhone()),User::getPhone,adminUpdateVo.getPhone())
                .set(StringUtils.isNotBlank(adminUpdateVo.getPassword()),User::getPassword,passwordEncoder.encode(adminUpdateVo.getPassword()))
                .set(adminUpdateVo.getStatus()!=null,User::getAccountStatus,adminUpdateVo.getStatus());
        int update = userMapper.update(null, wrapper);
        if (update==0){
            return AjaxResult.error("管理员编辑失败");
        }
        return AjaxResult.success();
    }

    //管理员删除
    @Override
    public AjaxResult deleteAdmin(Integer id) {
        int deleteById = userMapper.deleteById(id);
        if (deleteById==0){
            return AjaxResult.error("删除失败");
        }
        return AjaxResult.success();
    }

    //管理员模糊及分页查询
    @Override
    public AjaxResult likeListAdmin(LikeListAdminVo likeListAdminVo) {

        Page<User> page = new Page<>(likeListAdminVo.getPage(), likeListAdminVo.getSize());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getType,1);
        wrapper.like(StringUtils.isNotBlank(likeListAdminVo.getName()),User::getName,likeListAdminVo.getName());
        wrapper.like(StringUtils.isNotBlank(likeListAdminVo.getPhone()),User::getPhone,likeListAdminVo.getPhone());
        wrapper.eq(likeListAdminVo.getStatus()!=null,User::getAccountStatus,likeListAdminVo.getStatus());
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        List<User> records = userPage.getRecords();
        if (records.size()==0){
            return AjaxResult.error("未搜到该管理员或暂未添加管理员");
        }
        return AjaxResult.success(records);
    }

    //经销商下拉框
    @Override
    public AjaxResult selectBusiness() {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getAccountStatus,1);
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        return AjaxResult.success(users);
    }

    //模糊查询
    @Override
    public AjaxResult likeList(UserListVo userListVo) {
        //模糊查询  条件封装
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        Page<User> page = new Page<>(userListVo.getPage(),userListVo.getSize());
        //经销商名称
        wrapper.like(StringUtils.isNotBlank(userListVo.getBusinessName()),User::getBusinessName,userListVo.getBusinessName());
        //负责人
        wrapper.like(StringUtils.isNotBlank(userListVo.getName()),User::getName,userListVo.getName());
        //手机号
        wrapper.like(StringUtils.isNotBlank(userListVo.getPhone()),User::getPhone,userListVo.getPhone());
        //状态
        wrapper.eq(userListVo.getAuditStatus()!=null,User::getAuditStatus,userListVo.getAuditStatus());

        //禁用状态不显示
        wrapper.eq(User::getAccountStatus,1);
        //管理员身份不显示
        wrapper.eq(User::getType,0);
        if (!StringUtils.isNotBlank(userListVo.getBusinessName()) && !StringUtils.isNotBlank(userListVo.getName()) && !StringUtils.isNotBlank(userListVo.getPhone()) && userListVo.getAuditStatus()==null){
            return AjaxResult.error("请传入参数");
        }
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        List<User> users = userPage.getRecords();


        if (users.size()==0){
            return AjaxResult.error("未找到此经销商");
        }

        ArrayList<UserListDto> dtos = new ArrayList<>();

        for (int i = 0; i < users.size(); i++) {
            User user = users.get(i);
            UserListDto userListDto = new UserListDto();
            BeanUtils.copyProperties(user,userListDto);
            dtos.add(userListDto);
        }

        return AjaxResult.success("查询成功", dtos);
    }

    //分页查询
    @Override
    public AjaxResult pageInfo(UserPageVo userPageVo) {
        Page<User> page = new Page<>(userPageVo.getPage(), userPageVo.getSize());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //禁用状态不显示
        wrapper.eq(User::getAccountStatus,1);
        //管理员身份不显示
        wrapper.eq(User::getType,0);
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        List<User> users = userPage.getRecords();

        ArrayList<UserListDto> dtos = new ArrayList<>();

        for (int i = 0; i < users.size(); i++) {
            User user = users.get(i);
            UserListDto userListDto = new UserListDto();
            BeanUtils.copyProperties(user,userListDto);
            dtos.add(userListDto);
        }
        return AjaxResult.success("查询成功",dtos);
    }

    //逻辑删除
    @Override
    public AjaxResult deleteById(Integer id) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",id).set("account_status",0);
        int update = userMapper.update(null, wrapper);
        if (update==0){
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    //修改信息
    @Override
    public AjaxResult updateOne(UserUpdateVo userUpdateVo) {

        if (!StringUtils.isNotBlank(userUpdateVo.getBusinessName())){
            return AjaxResult.error("编辑失败",HttpStatus.BAD_REQUEST);
        }

        if (!StringUtils.isNotBlank(userUpdateVo.getName())){
            return AjaxResult.error("编辑失败",HttpStatus.BAD_REQUEST);
        }

        if (!StringUtils.isNotBlank(userUpdateVo.getPhone())){
            return AjaxResult.error("编辑失败",HttpStatus.BAD_REQUEST);
        }
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",userUpdateVo.getId())
                .set(StringUtils.isNotBlank(userUpdateVo.getBusinessName()),"business_name",userUpdateVo.getBusinessName())
                .set(StringUtils.isNotBlank(userUpdateVo.getName()),"name",userUpdateVo.getName())
                .set(StringUtils.isNotBlank(userUpdateVo.getPhone()),"phone",userUpdateVo.getPhone())
                .set(StringUtils.isNotBlank(userUpdateVo.getPassword()),"password",userUpdateVo.getPassword())
                .set(StringUtils.isNotBlank(userUpdateVo.getEmail()),"email",userUpdateVo.getEmail())
                .set(StringUtils.isNotBlank(userUpdateVo.getCity()),"city",userUpdateVo.getCity())
                .set(StringUtils.isNotBlank(userUpdateVo.getEquipment()),"equipment",userUpdateVo.getEquipment())
                .set(StringUtils.isNotBlank(userUpdateVo.getServiceDesk()),"service_desk",userUpdateVo.getServiceDesk());

        int update = userMapper.update(null, wrapper);
        if (update==0){
            return AjaxResult.error();
        }

        return AjaxResult.success();

    }

    //审核
    @Override
    public AjaxResult audi(UserAudiVo userAudiVo) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",userAudiVo.getId())
                .set("audit_status",userAudiVo.getAuditStatus())
                .set("remarks",userAudiVo.getRemarks());
        int update = userMapper.update(null, wrapper);
        if (update==0){
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    //账号退出
    @Override
    public AjaxResult logout() {
        //获取SecurityContextHolder中的用户id
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Integer userId = loginUser.getUser().getId();

        //删除redis中的值
        redisCache.deleteObject("login:"+userId);
        return AjaxResult.success();
    }




}
